#include "../logs/lcglog.h"
#include <vector>
#include <thread>
#include <chrono>
/*参数：日志器名称，线程总数量，日志总数量，单条日志大小*/
void bench(const std::string& name, size_t thr_count, size_t msg_count, size_t msg_len){
    //1.获取日志器
    lcglog::Logger::ptr logger = lcglog::getLogger(name);
    if(logger.get() == nullptr){
        return;
    }
    std::cout << "测试日志：" << msg_count << " 条, 总大小:" << msg_count * msg_len / 1024 <<
        "KB" << std::endl;

    //2.组织指定长度的日志消息
    std::string msg(msg_len - 1, 'A');//最后一个字节是换行符，以便于输出打印
    //3.创建指定数量的线程
    size_t msg_per_thr = msg_count / thr_count;//一个线程要写的日志数量--每个线程输出的日志条目
    std::vector<std::thread> threads;
    std::vector<double> cost_array(thr_count);
    for(int i=0; i<thr_count; i++){
        threads.emplace_back([&, i](){
            //4.线程函数内部开始计时
            auto start = std::chrono::high_resolution_clock::now();
            //5.开始循环写日志
            for(int j=0; j<msg_per_thr; j++){
                logger->fatal("%s", msg.c_str());
            }
            //6.线程函数内部结束计时
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> cost = end - start;
            cost_array[i] = cost.count();
            std::cout << "\t线程[" << i << "]: " << "  输出日志数量:" << msg_per_thr << ", 耗时:" << 
                cost.count()  << "s" << std::endl;
        });
    }
    for(int i=0; i<thr_count; i++){
        threads[i].join();
    }
    //7.计算总耗时-所有写线程中所耗时间最多的那个线程
    /*多线程中每个线程都有自己的运行时间，但线程是并发处理的，因此耗时最多的那个才是总时间*/
    double cost_max = cost_array[0];
    for(int i=0; i<thr_count; i++){
        cost_max = cost_max < cost_array[i] ? cost_array[i] : cost_max;
    }
    size_t msg_per_sec = msg_count / cost_max;
    size_t size_per_sec = (msg_count * msg_len) / (cost_max*1024);
    //8.进行输出打印
    std::cout << "\t总耗时: " << cost_max << "s" << std::endl;
    std::cout << "\t每秒输出日志数量: " << msg_per_sec  << " 条"  << std::endl;
    std::cout << "\t每秒输出日志大小: " << size_per_sec << " KB" << std::endl; 
}

void sync_bench(){
    std::unique_ptr<lcglog::LoggerBuilder> builder(new lcglog::GlobalLoggerBuilder());
    builder->buildLoggerName("sync_logger");
    builder->buildLoggerLevel(lcglog::LogLevel::value::DEBUG);
    builder->buildLoggerFormatter("%m%n");
    builder->buildLoggerType(lcglog::LoggerType::LOGGER_SYNC);
    builder->buildSink<lcglog::FileSink>("./logfile/sync.log");
    builder->build();
    bench("sync_logger", 5, 1000000, 100);
}
void async_bench(){
    std::unique_ptr<lcglog::LoggerBuilder> builder(new lcglog::GlobalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildLoggerLevel(lcglog::LogLevel::value::DEBUG);
    builder->buildLoggerFormatter("%m%n");
    builder->buildLoggerType(lcglog::LoggerType::LOGGER_ASYNC);
    builder->buildEnableUnsafeAsync();//开启非安全模式-主要是将实际落地时间排除在外
    builder->buildSink<lcglog::FileSink>("./logfile/async.log");
    builder->build();
    bench("async_logger", 5, 1000000, 100);
}
int main(){
    async_bench();
    return 0;
}